package com.zerocarbon.framework.web.handler;

import com.alibaba.fastjson.JSON;
import com.zerocarbon.framework.common.constants.CommonConstant;
import com.zerocarbon.framework.common.constants.ContextConstants;
import com.zerocarbon.framework.common.dto.BaseDTO;
import com.zerocarbon.framework.common.enums.BaseExceptionCode;
import com.zerocarbon.framework.common.result.Result;
import com.zerocarbon.framework.common.result.vo.AuthTokenVO;
import com.zerocarbon.framework.common.utils.RestUtil;
import com.zerocarbon.framework.core.context.UserContextHandler;
import com.zerocarbon.framework.core.extension.IAppSecretUtil;
import com.zerocarbon.framework.core.jwt.TokenService;
import com.zerocarbon.framework.web.extension.ValidateResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Map;

/**
 * 用户签名、token验证实现类
 * @author wyf  2020年6月17日
 */
@Slf4j
public class ValidRestHandler implements IValidRestHandler {
	
	@Autowired
    private TokenService tokenService;
	
	@Autowired
	private IAppSecretUtil iAppSecretUtil;

	/**
	 * 根据appkey获取应用密钥
	 */
	public String getAppSecret(String appKey) {
		return iAppSecretUtil.getAppSecretByAppKey(appKey);
	}

	/**
	 * 验证签名
	 */
	@Override
	public <T> ValidateResult<T> validateSgin(BaseDTO param, String appSecret) {
		log.debug("IRestParam-param：=" + JSON.toJSONString(param));
		Map<String, String> params = RestUtil.jsonToMap(JSON.toJSONString(param));
		if(!RestUtil.validateSgin(params, appSecret)) {
			log.error("[validateSgin] sgin fail, param.sign="+ params.get(CommonConstant.DEFAULT_SIGN_PARAM) +" str=" + RestUtil.getParamStrForSign(params, appSecret) + " "
					+ "valid.sign=" + RestUtil.sign(RestUtil.getParamStrForSign(params, appSecret), CommonConstant.DEFAULT_CHARSET_UTF8));
			
			return new ValidateResult<T>(false, Result.fail(BaseExceptionCode.SGIN_EX.getCode(), BaseExceptionCode.SGIN_EX.getMessage()));
		} else
			return new ValidateResult<T>(true);
	}

	/**
	 * 验证用户认证
	 */
	@Override
	public <T> ValidateResult<T> validateAuth(String authorization) throws Exception {
		if(UserContextHandler.getUserId() > 0l && UserContextHandler.getTenantId() > 0l) 	//上下文有用户信息，说明已经验证过token直接放行
			return new ValidateResult<T>(true);
			
		final String openAuthTokenStart = "OpenAuthorization ";
		if (StringUtils.isNotEmpty(authorization) && authorization.startsWith(ContextConstants.BEARER_HEADER_PREFIX) && authorization.length()>7) {
			//解析token
			AuthTokenVO authTokenVO = tokenService.getAuthTokenVO(authorization);
			if(authTokenVO==null || authTokenVO.getUserId()==null || authTokenVO.getTenantId()==null) { //用户信息不正确
				return new ValidateResult<T>(false, Result.fail(BaseExceptionCode.TOKEN_INVALID_EX.getCode(), BaseExceptionCode.TOKEN_INVALID_EX.getMessage()));
        	}
        	//更新用户信息上下文
        	this.updateUserContext(authTokenVO);
        	
        	//需要在验证token是否拉黑名单
        	/*if(CommonConstants.USER_TYPE_C.equals(restParam.getRestContext().getUserType())) { //C端客户，判断是否进入黑名单
        		MemberToken memberToken = memberTokenUtil.getMemberTokenCacheById(restParam.getRestContext().getTokenUuid(), CommonConstants.USER_TYPE_C);
        		if(memberToken.getTokenStatus().intValue()==1) //进入黑名单
        			return new ValidateResult<T>(false, RestRequestResult.wrapErrorResponse(RestConstants.ERROR_CODE_TOKEN_LOGOUT, RestConstants.getMessage(RestConstants.ERROR_CODE_TOKEN_LOGOUT)));
        	}*/
		}
		else if(StringUtils.isNotEmpty(authorization) && authorization.startsWith(openAuthTokenStart) && authorization.length()>18){
			//小程序token解析
			//authorization = authorization.substring(openAuthTokenStart.length());
			//return validateAndSetContextByOpenAuth(param, authorization);
			return new ValidateResult<T>(true);
		}
		else {
			return new ValidateResult<T>(false, Result.fail(BaseExceptionCode.TOKEN_PARSER_FAIL_EX.getCode(), BaseExceptionCode.TOKEN_PARSER_FAIL_EX.getMessage()));
		}
		return new ValidateResult<T>(true);
	}
}
